package org.example.proxy;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetSocket;
import org.example.RpcApplication;
import org.example.config.RpcConfig;
import org.example.constant.RpcConstant;
import org.example.fault.retry.RetryStrategy;
import org.example.fault.retry.RetryStrategyFactory;
import org.example.fault.tolerant.TolerantStrategy;
import org.example.fault.tolerant.TolerantStrategyFactory;
import org.example.loadbalancer.LoadBalancer;
import org.example.loadbalancer.LoadBalancerFactory;
import org.example.pojo.RpcRequest;
import org.example.pojo.RpcResponse;
import org.example.pojo.ServiceMetaInfo;
import org.example.protocol.*;
import org.example.registry.Registry;
import org.example.registry.RegistryFactory;
import org.example.serializer.Serializer;
import org.example.serializer.SerializerFactory;
import org.example.serve.tcp.TcpBufferHandlerWrapper;
import org.example.serve.tcp.VertxTcpClient;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class ServiceProxy implements InvocationHandler {
    /**
     * 代理方法
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//        Serializer jdkSerializer = new JdkSerializer();
        RpcConfig rpcConfig = RpcApplication.getRpcConfig();
        //获取序列化器
        Serializer serializer = SerializerFactory.getInstance(rpcConfig.getSerializer());
        //封装请求对象
        RpcRequest rpcRequest = new RpcRequest();
        rpcRequest.setServiceName(method.getDeclaringClass().getName());
        rpcRequest.setMethodName(method.getName());
        rpcRequest.setParameters(args);
        rpcRequest.setParameterTypes(method.getParameterTypes());
        //从配置中获取服务注册中心地址
        Registry registry = RegistryFactory.getInstance(rpcConfig.getRegistryConfig().getRegistryType());
        ServiceMetaInfo serviceMetaInfo = new ServiceMetaInfo();
        serviceMetaInfo.setServiceName(method.getDeclaringClass().getName());
        serviceMetaInfo.setServiceVersion(RpcConstant.DEFAULT_SERVICE_VERSION);
        List<ServiceMetaInfo> serviceMetaInfos = registry.serviceDiscovery(serviceMetaInfo.getServiceKey());
        if (CollUtil.isEmpty(serviceMetaInfos)){
            throw new RuntimeException("未发现服务");
        }
        //负载均衡
        LoadBalancer loadBalancer = LoadBalancerFactory.getInstance(rpcConfig.getLoadBalancer());
        HashMap<String, Object> requestParams = new HashMap<>();
        requestParams.put("method", rpcRequest.getMethodName());
        ServiceMetaInfo select = loadBalancer.select(requestParams, serviceMetaInfos);

        //发送请求
//        HttpResponse execute = HttpRequest.post(serviceMetaInfo1.getServiceAddress()).body(serialize).execute();
//        byte[] bytes = execute.bodyBytes();
//        RpcResponse rpcResponse = serializer.deserialize(bytes, RpcResponse.class);
//        return rpcResponse.getData();
        // 发送TCP请求(优化)
        //使用重试机制
        RpcResponse rpcResponse;
        try {
            RetryStrategy retryStrategy = RetryStrategyFactory.getInstance(rpcConfig.getRetryStrategy());
            rpcResponse = retryStrategy.doRetry(() -> VertxTcpClient.doRequest(rpcRequest, select));
        } catch (Exception e) {
            TolerantStrategy tolerantStrategy = TolerantStrategyFactory.getInstance(rpcConfig.getTolerantStrategy());
           rpcResponse=tolerantStrategy.doTolerant(null, e);
        }
        return rpcResponse.getData();
    }
}
